<?php
	
	final class Interface_Fmgr0v0r01 extends _smuoiAppInterface{
		
		protected $base;
		protected $fmrp;
		protected $file;
		
		protected $fmgr;
		protected $db;
	
		function readRequest($rf){
			$a = explode('/', $rf);
			$base = array_shift($a);
			if(substr($base, 0, 1) != '@'){
				$base = 'desk:/'.$base;
				$fmrp = 'desk:/'.$rf;
			}else{
				$base = substr($base, 1).':/';
				$fmrp = $base.implode('/', $a);	
			}
			//var_dump($base, $fmrp); exit;
			$this->base = $base;
			$this->fmrp = $fmrp;
		}
	
		function load(){
			$this->readRequest($this->args->rf);
			if(!$base = $this->pkg->open($this->base)) httpE(404, "No file at base ".$this->base);
			if($this->pkg->test_instanceof($base, 'mnt')){
				if(!$target = $base->target()) httpE(404, $this->base." has missing target");
				$remainder = substr($this->fmrp, strlen($this->base));
				$this->fmrp = $target->smrf;
				$this->fmrp = (((substr($this->fmrp, -1) == '/')&& $remainder) ? substr($this->fmrp, 0, -1) : $this->fmrp).$remainder;
				//var_dump($this->fmrp);
				$file = smrf($this->fmrp);
			}else $file = $this->pkg->open($this->fmrp);
			if(!$file) httpE(404, "No file at fmrp ".$this->fmrp);
			if(!smuoi_is_readable($file)) httpE(401, "No read access to ".$this->fmrp);
			$this->fmgr = $file->pkg;
			$this->db = $file->db();
			$this->file = $file;
			if(!$this->args->icon) $this->args->icon = $this->file->icon();
		}
		
		function run(){
			switch(true){
				case isset($_GET['fmgr_upload']):
					die($this->parse_include('Screens/upload-iframe.php'));
				case isset($_GET['force_download']):
					die($this->parse_include('Screens/force-download.php'));					
			}
			$this->load();
			if(DOAJAX) return $this->run_ajax();
			$app = $this->getScreen($this->file);
			$this->run_screen($app);	
		}
		
#======	GUI ============================
		
		function getScreen($file){
			switch(true){
				case(smuoi_is_dir($file)):
					return 'DirView';
				case(smuoi_is_text($file)):
					return 'SmuoiText';
				case(smuoi_is_image($file)):
					return 'ImageEdit';
				default:
					return 'FileView';
			}
		}

		function title(){
			return ($this->file) ? $this->file->fmrp : 'Unknown Location';
		}
		
		function description(){
			return $this->file->media_class;
		}
		
		function build_nav_element(){
			// Build the navigation element
			$a = explode('/', ARF);
			if(!$last = array_pop($a)) return 'desk: /';
			$href = '/#';
			$nav = '<a href="/#">desk:</a> / ';
			foreach($a as $i=>$h){
				$href .= "$h/";
				$nav .= '<a href="'.$href.'">'.$h.'</a> / ';
			}
			$nav .= $last;
			return $nav;
		}
		
		
#======	AJAX ============================
		
		protected $ajax_methods = array(
			// BROWSER
			'browse',
			'userExpectUpload',						 
			'findUnames',
			'setPermissions',
			
			// DIRECTORY
			'dir_open',
			'get_children', 
			'get_latest_children',
			'newChild', 
			'paste', 
			'trashFiles',
			'duplicate',
			'empty_trash',
			'pack',
			'unpack',
			'newlink',
			'newsym',
			
			// GENERIC
			'saveFile', 
			'saveTo', 
			'renameFile', 
			'newDraft', 
			'switchDraft', 
			'unDraft', 
			'overwrite',
			'usurp',
			'usurpas',

			// MISC
			'ping'
		);
		
		function fail401($t='write', $file=false){
			if(!$file) $file = $this->file;
			httpE(401, $this->notify401($t, $file, false));	
		}
		
		function fail405(){
			httpE(405, "Method not allowed on ".$this->file->fmrp);	
		}
		
		function notify401($t, $file, $e=true){
			$s = "You do not have $t access to <strong>$file->fmrp</strong><br />";
			if($e) echo $s;
			else return $s;
		}
	
		function browse($xa){
			switch($xa->get('query')){
				case 'moreinfo':
					return $this->browse_permissions($xa);
				default:
					if(!$this->file->dir) httpE(418, 'woops!');
					$j = $this->json_children();				
					jsln("Browser.receive($j);");
			}	
		}
		
####	BROWSER
		
		function userExpectUpload($xa){
			$a = sn()->session()->auxiliary_data();
			$aa = !is_array($a->uploadtokens) ? array() : $a->uploadtokens;
			array_push($aa, $xa->token);
			$a->set('uploadtokens', $aa);
			$a->write();
		}
		
		function browse_permissions($xa){
			global $items,$owner,$group;
			foreach($xa->ids as $id) $items[] = $this->db->get($id);
			$s = $this->parse_include('Screens/browse-fileinfo.php', false, true);
			jsln("Browser.receive(".json_encode($s).");");
			if(!is_root()) return;
			$j = new json;
			foreach($items as $item) $j->set($item->id, $item->summary());
			$owner = json_encode($owner);
			$group = json_encode($group);
			jsln("PermsSet.load($j, $owner, $group);");
		}
		
		function findUnames($xa){
			if(!is_root()) return;
			$r = new obj;
			$locObj = smdb()->open();
			$n = $xa->name;
			$t = $xa->type;
			$users =  (strlen($n) < 3) ? 
				$locObj->select(array('id', 'name'), 'users', array('name'=>$n)) : 
				$locObj->select(array('id', 'name'), 'users', array('%name'=>"$n%"));
			switch($t){
				case 'owner':
					if($users) 
						foreach($users as $user) $r->set($user['name'], $user['id']);
					break;
				case 'group':
					if($users) 
						foreach($users as $user) 
							if($group = $locObj->select(array('id'), 'groups', array('nam'=>':'.$user['id']))) 
								$r->set($user['name'], $group[0]['id']);						
					$groups = (strlen($n) < 3) ?
						$locObj->select(array('id', 'nam'), 'groups', array('nam'=>$n)) : 
						$locObj->select(array('id', 'nam'), 'groups',  array('%nam'=>"$n%"));
					if($groups) 
						foreach($groups as $group) 
							if(substr($group['nam'], 0, 1) != ':') $r->set($group['nam'], $group['id']);
					break;
			}
			$r = json_encode($r);
			jsln("PermsSet.receiveUnames('$t', '$n', $r);");
		}
		
		function setPermissions($xa){
			if(!is_root()) return;
			$own = (isset($xa->own)) ? smdb($xa->own) : false;
			$grp = (isset($xa->grp)) ? smdb($xa->grp) : false;
			foreach($xa->ids as $id){
				$obj = $this->db->get($id);
				if($own) $obj->own = $own;
				if($grp) $obj->grp = $grp;
				if(isset($xa->mod)) $obj->mod = $xa->mod;
				if(isset($xa->stb)) $obj->stb = $xa->stb;
				if(isset($xa->rcr)) $obj->mode_recurse = $xa->rcr;
				$obj->commit();
			}
			$this->get_latest_children($xa);
			$this->browse_permissions($xa);
		}
		
####	DIRECTORY
	
	
		function dir_open($xa){
			if(!smuoi_is_dir($this->file)) $this->fail405('not a dir');
			if(!$this->file->is_executable) $this->fail401("execute");
			$j = new json($this->file->summary(1));
			if($this->args->is_app_base && $this->args->icon) $j->icon = $this->args->icon;
			$j->navigation = $this->build_nav_element();;
			jsln("Dir.load($j);");
			$this->get_children();
		}
		
		function json_children(){
			$j = new json;
			foreach($this->file->children() as $f) $j->set($f->id, $f->summary());
			return $j;
		}
	
		function get_children(){
			jsln('Dir.load_contents('.$this->json_children().');');
		}
	
		function get_latest_children(){
			$s = 120;
			$d = $this->file;
			$t = $this->fmgr->table('files');
			if(!$files = $this->db->open()->execute("SELECT `id` FROM `$t` WHERE `updated` > ".(time()-$s)." AND `fmrp` REGEXP '".$d->cdrn_regexp()."';")) return;
			$j = new json;
			foreach($files as $row){
				$c = $this->db->get($row['id'])->summary();
				$j->set($c->id, $c);	
			}
			jsln("Dir.append($j);");
		}
	
		function newChild($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			switch($xa->type){
				case 'dir':
					$new = $this->file->mkdir('untitled directory');
					break;
				case 'fil':
					$new = $this->file->mkfil('untitled.html');
					break;
			}
			if(!$new) httpE(418, 'Damn!');
			$j = new json($new->id, $new->summary());
			jsln("Dir.append($j);");
		}
		
		function renameFile($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			if(!$fil = $this->db->get($xa->id)) httpE(404);
			if(!$fil->is_writable) $this->fail401('write', $fil);
			$fil->basename = $xa->basename;
			$fil->commit();
			$j = new json($fil->id, $fil->summary());
			jsln("Dir.append($j);");
		}
		
		function paste($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			$j = new json;
			$c = false;
			$pars = array();
			foreach($xa->items as $fmrp){
				if(!$f = smrf($fmrp)) continue;
				if($f->parent() === $this->file) continue;
				$pars[] = $f->parent()->id;
				switch($xa->action){
					case 'cut':
						$c = $this->file->appendChild($f);
						break;
					case 'copy':
						$c = $f->copy_to($this->file);
						break;
				}
				if($c) $j->set($c->id, $c->summary());
			}
			jsln("Clipboard.clear();");
			foreach(array_unique($pars) as $par) jsln("Loader.uncache('$par');");
			jsln("Dir.append($j);");
		}
		
		function trashFiles($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			$Trash = $this->fmgr->open('desk:/trash');
			foreach($xa->ids as $id){
				$fil = $this->db->get($id);
				if($fil->class == 'symdir') $fil->destroy();
				elseif(!$Trash->appendChild($fil)) httpE(418, "Could not trash file <strong>$fil->fmrp</strong>");
			}
			$this->get_children();
		}
		
		function duplicate($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			foreach($xa->ids as $id){
				$fil = $this->db->get($id);
				if(!$fil->is_readable){
					$this->notify401('read', $fil);
					continue;	
				}
				$fil->duplicate();
			}
			$this->get_latest_children();
		}
		
		function empty_trash(){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			$T = $this->fmgr->open('desk:/trash');
			$T->purge();
			$j = new json($T->summary());
			jsln("Dir.load($j);");
			$this->get_children();
		}
		
		function pack($xa){
			if(!$this->file->dir) $this->fail405();
			if(!$this->file->is_writex()) $this->fail401();
			include_once($this->fmgr->path_to_libclass('TarIndex'));
			$index = new TarIndex($xa->ids, true, true, $this->db->DOM);
			$index->copy();
			$index->scrape();
			$gz = $index->pack();
			if(!$new = $this->file->appendChild($gz)) httpE(418, "Bugger.  Failed to stat $gz");
			$index->cleanup();
			$j = new json($new->id, $new->summary());
			jsln("Dir.append($j);");
		}
		
		function unpack($xa){
			$tgz = $this->db->get($xa->id);
			$tgz->unpack();
			$this->get_children();
		}
		
		function newlink($xa){
			$target = ($smrf = trim($xa->get('smrf'))) ? smrf($smrf) : $this->file;
			$parent = (!$smrf) ? $this->pkg->open('desk:/') : $this->file;
			if(!$target) httpE(404, "$smrf wasn't found");
			$class = ($target->dir && ($parent->class == 'Desk')) ? 'mnt' : 'lnk';
			$args = array(
				'app_class'=>$class,
				'smrf'=>$target->smrf()
			);
			if(!$bas = $target->basename) $bas = basename($target->smrf());
			$name = str_replace(array(' ', '.'), '', $bas);
			$lnk = filename_increment($parent->realpath($name));
			$ini = new ini($lnk, $args);
			$ini->write();
			$o = $parent->pkg->build_file($lnk);
			$o->class = $class; 
			$new = $parent->appendChild($o);
			if($this->file->dir){
				$j = new json($new->id, $new->summary());
				jsln("Dir.append($j, '".$parent->id."');");
			}else echo 'Done.';
		}
		
		function newsym($xa){
			if(!usr()->can_symlink()) $this->fail401();
			if(!$this->file->dir) $this->fail405();
			$path = $xa->path;
			if(!file_exists($path)){
				echo "$path does not exist";
				return;
			}
			if(!is_readable($path)){
				echo "$path is not readable";
				return;
			}
			foreach(array('docs', 'desk', 'temp') as $k){
				$d = $this->fmgr->rootdir($k);
				if(substr(strtolower($d), 0, strlen($path)) !== strtolower($path)) continue;
				echo "$path is parent to $d";
				return;
			}
			$dest = filename_increment($this->file->realpath(basename($path)));
			symlink($path, $dest);
			if(!$new = $this->file->appendChild($dest)) httpE(418, "Bugger.  Failed to create $dest");
			$j = new json($new->id, $new->summary());
			jsln("Dir.append($j);");
		}
		
####	SMUOITEXT / IMAGEEDIT
	
		function saveFile($xa){
			$file = ($id = $xa->get('id')) ? $this->db->get($id) : $this->file;
			if(!$file->is_writable) $this->fail401('write', $file);
			$this->runFileSaveObject($file, $xa);
			$file->commit();
			$d = new json($file->summary(2));
			jsln("File.load($d); Drafts.draw();");
		}

		function saveTo($xa){
			if(!$this->file->is_writex()) $this->fail401();
			$fil = fmrp($xa->fmrp);
			if(!$fil->is_readable) $this->fail401('read', $fil);
			if($xa->get('victim')){
				if($victim = fmrp($xa->victim)) $this->file->removeChild($victim);
			}
			if(!$new = $fil->copy_to($this->file)) httpE(418, 'failed to duplicate');
			$this->runFileSaveObject($new, $xa);
			$new->commit();
			jsln("goTo('".$new->deskpath().");");
		}
	
		function runFileSaveObject($fil, $xa){
			if(!isset($xa->set)) return;
			foreach($xa->set as $k=>$v) $fil->$k = $v;
		}	
			
		function newDraft($xa){
			if(!$this->file->is_writable) $this->fail401();
			$Drafts = $this->fmgr->open('temp:/drafts');
			if(!$draft = $Drafts->do_draft($this->file, $xa->cur)) httpE(418, 'Could not redraft');
			$this->runFileSaveObject($draft, $xa);
			$draft->commit();
			$d = new json($draft->summary(1));
			$i = new json($Drafts->index_of($this->file));
			jsln("File.load($d); Drafts.load($i);");
		}
		
		function switchDraft($xa){
			$draft = $this->db->get($xa->id);	
			$d = new json($draft->summary(2));
			jsln("File.load($d); Drafts.draw();");
		}
		
		function unDraft($xa){
			if(!$this->file->is_writable) $this->fail401();
			$Drafts = $this->fmgr->open('temp:/drafts');
			if($xa->draft_id){
				$dfil = $this->db->get($xa->draft_id);
				if(!$Drafts->discard($this->file, $dfil)) echo 'Could not discard draft<br />';
			}else{
				if(!$Drafts->undraft($this->file)) echo 'Could not undraft<br />';
			}
			$i = new json($Drafts->index_of($this->file));
			$draft = $Drafts->latest_of($this->file);
			$d = new json($draft->summary(1));
			jsln("File.load($d); Drafts.load($i); File.showInfo();");
		}
		
		function overwrite($xa){
			if(!$this->file->is_writable) $this->fail401();
			$dfil = $this->db->get($xa->draft_id);
			$Drafts = $this->fmgr->open('temp:/drafts');
			$Drafts->rewrite($this->file, $dfil);
			return $this->saveFile($xa);
		}
		
		function usurp($xa){
			$this->file->usrp = $xa->usurpa;
			$this->file->commit();
			jsln("USURPA = '$xa->usurpa';");
			return $this->saveFile($xa);
		}
		
		function usurpas(){
			$s = json_encode($this->parse_include('Screens/show-usurpas.php'));
			jsln("TUXalert($s);");
		}

		function ping(){
			
		}
	}
	
?>
